<template>
  <div class="header_theme">
    <el-radio-group v-model="text" class="list">
      <el-row :span="24">
        <el-col v-for="(item,index) in themeList" :key="index" :md="4" :xs="12" :sm="4">
          <el-radio :label="item.value" @change="fn_radioChange">{{ item.name }}</el-radio>
        </el-col>
      </el-row>
    </el-radio-group>
    <div class="theme_edit_title">自定义样式编辑</div>
    <div v-for="(item, index) in themeColor" :key="index" class="color_select">
      {{ themeClolrName[index] }}：
      <el-color-picker
        size="mini"
        style="padding-right: 9px;"
        class="theme-picker"
        popper-class="theme-picker-dropdown"
        v-model="themeColor[index]"
        :predefine="predefineColors"
        @change="fn_colorChange"
      />
    </div>
  </div>
</template>

<script>
import { postDefaultTheme } from "@/api/desktop/index.js";
import { setTheme } from "@/util/util.js";
import { mapGetters } from "vuex";
const const_var = require("@/const/var.js");

export default {
  name: "HeaderTheme",

  data () {
    return {
      box: false,
      text: "",
      // 用户的主题列表
      themeList: [
        {
          name: "默认",
          value: "theme1-pink"
        },
        {
          name: "浅蓝",
          value: "theme2-blue"
        },
        {
          name: "灰色",
          value: "theme3-grey"
        },
        {
          name: "自定义",
          value: "theme-custom"
        }
      ],
      themeClolrName: {
        "color": "字体",
        "background-color": "背景颜色",
        "border-color": "边框颜色"
      },
      // 用户选择的定义颜色
      customTheme: {
        "color": "#ff6262",
        "background-color": "#ff6262",
        "border-color": "#ff6262"
      },
      // 最终需要的自定义属性
      finalTheme: {
        "color": "#ff6262",
        "background-color": "#ff6262",
        "border-color": "#ff6262"
      },
      predefineColors: [
        "#ff4500",
        "#ff8c00",
        "#ffd700",
        "#90ee90",
        "#00ced1",
        "#1e90ff",
        "#c71585"
      ]
    };
  },

  computed: {
    ...mapGetters(["themeName", "themeColor"])
  },

  watch: {
    text: function (val) {
      this.$store.commit("SET_THEME_NAME", val);
      setTheme(val);
    }
  },

  mounted () {
    this.text = this.themeName;
    this.fn_filterProp(this.themeColor);
    this.fn_cLick();
    this.postDefaultTheme();
  },

  methods: {
    // 设置主题标签到body上fn_
    fn_radioChange (val) {
      this.$store.commit("SET_THEME_NAME", val);
      this.postDefaultTheme();
    },
    // 自定义主题颜色改变
    fn_colorChange () {
      this.$store.commit("SET_THEME_COLOR", this.themeColor);
      this.fn_filterProp(this.themeColor);
      this.fn_cLick();
      this.postDefaultTheme();
    },
    // 修改默认主题
    postDefaultTheme () {
      let obj = {
        name: this.themeName,
        value: JSON.stringify(this.themeColor)
      };
      return postDefaultTheme(obj);
    },
    // 点击主题切换(主要获取link跟style的dom，并且获取有效的css链接)
    fn_cLick () {
      const head = document.getElementsByTagName("head")[0];
      const links = [].slice.call(head.getElementsByTagName("link"));
      const styles = [].slice.call(head.getElementsByTagName("style"));
      const cssFilterLinks = [];
      const cssLinks = links.filter(item => item.href.includes("css"));

      // 获取需要用到的链接
      cssLinks.forEach(item => {
        if (!cssFilterLinks.includes(item.href)) {
          cssFilterLinks.push(item.href);
        }
      });

      // 加载link样式并且生成style
      for (let i = 0; i < cssFilterLinks.length; i++) {
        this.getCSSString(cssFilterLinks[i], innerText => {
          innerText = this.fn_Style(innerText);
          let styleTag = document.getElementById(i);
          if (!styleTag) {
            styleTag = document.createElement("style");
            styleTag.type = "text/css";
            styleTag.id = i;
            styleTag.innerHTML = innerText;
            head.appendChild(styleTag);
          }
        });
      }

      // 修改style样式
      styles.forEach((style, index) => {
        const { innerText } = style;
        if (typeof innerText !== "string") {
          return;
        }
        style.innerText = this.fn_Style(innerText);
      });

      // 将css的link链接删除(等待dom加载完成再删除)
      this.$nextTick(() => {
        setTimeout(() => {
          cssLinks.forEach(item => {
            head.removeChild(item);
          });
        }, 1000);
      });
    },
    // 异步获取link链接的样式
    getCSSString (url, callback, variable) {
      const xhr = new XMLHttpRequest();
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4 && xhr.status === 200) {
          if (variable) {
            this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
          }
          let newArr = xhr.responseText.replace(/\.\.\//g, `${const_var.BASEURL}/`);
          callback(newArr);
        }
      };
      xhr.open("GET", url);
      xhr.send();
    },
    // 替换样式
    fn_Style (style) {
      const themeFeature = "#theme-custom";
      const REX = /\{(.+?)\}/g;
      let REXResult = [];
      let propObj = {};
      let propObjKeys = "";
      let newStyle = style.replace(/\n/g, "").split("}");
      newStyle.pop();

      newStyle.forEach((item, index) => {
        newStyle[index] += "}";
        if (item.includes(themeFeature)) {
          // if(index !== 68) return
          REXResult = newStyle[index].match(REX);
          propObj = REXResult[0].slice(1, -1).replace(/\s/g, "").split(";").filter(i => i.length > 0);
          propObj = propObj.map(j => j.split(":"));
          propObj = Object.fromEntries(propObj);
          propObjKeys = Object.keys(propObj);
          for (let prop in this.finalTheme) {
            if (propObjKeys.includes(prop)) {
              propObj[prop] = this.finalTheme[prop];
            }
          }

          let newStr = "";
          for (let key in propObj) {
            newStr = `${key}:${propObj[key]};`;
          }
          newStr = `{${newStr}}`;
          newStyle[index] = newStyle[index].replace(/\{(.*)+\}/g, newStr);
        }
      });
      newStyle = newStyle.join("");
      return newStyle;
    },
    // 获得最终的对比定义颜色数据
    fn_filterProp (theme) {
      // 将用户选择的定义颜色传值给最终的对比数据
      Object.keys(theme).forEach(item => {
        this.finalTheme[item] = theme[item];
      });

      // 对边框颜色进行对比
      if ("border-color" in theme) {
        this.finalTheme["border-top-color"] = theme["border-color"];
        this.finalTheme["border-bottom-color"] = theme["border-color"];
        this.finalTheme["border-left-color"] = theme["border-color"];
        this.finalTheme["border-right-color"] = theme["border-color"];
      }
    }
  }
};
</script>

<style lang="less">
.header_theme {
  .list {
    width: 100%;
  }
  .theme_edit_title {
    margin: 10px 0;
    padding-top: 10px;
  }
  .color_select {
    margin-top: 10px;
    display: flex;
    line-height: 28px;
  }
}
</style>
